﻿package com.bizmlib.ui.scrolling
{
	import flash.display.InteractiveObject;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	
	[Event(name="scrollInvoked", type="com.bizmlib.ui.scrolling.ScrollerEvent")]
	
	
	public class SimpleScroller extends AbstractScroller
	{
		protected var ARROW_AREA_HEIGHT:Number = 11;
		protected var HEIGHT_INITIAL:Number = 200;
		protected var SCROLL_STEP_INITIAL:Number = .05;
		//protected var LINKAGEID_ARROW_UP:String = "ScrollerArrow";
		//protected var LINKAGEID_ARROW_DN:String = "ScrollerArrow";
		//protected var LINKAGEID_SLIDER:String = "ScrollerSlider";
		protected var classArrowUp:Class;
		protected var classArrowDn:Class;
		protected var classSlider:Class;
	
		protected var arrowUp:InteractiveObject;
		protected var arrowDn:InteractiveObject;
		protected var slider:AbstractSlider;
	
		protected var __height:Number;
		protected var trackY1:Number;
		protected var trackY2:Number;
		protected var trackHeight:Number;
		protected var scrollStep:Number;
		
		protected var flipArrowDnVertically:Boolean = false;
	
	
		public function SimpleScroller()
		{
		}
	
	
		override public function set height(value:Number):void
		{
			//trace(this + ".height (set) " + arguments);
	
			setHeightValue(value);
			updateHeight();
			updatePosition();
		}
		override public function get height():Number
		{
			return __height;
		}
		protected function setHeightValue(value:Number):void
		{
			//trace(this + ".setHeightValue(" + arguments + ")");
	
			__height = Math.max(value, 2*ARROW_AREA_HEIGHT);
	
			trackY1 = ARROW_AREA_HEIGHT;
			trackHeight = Math.max(2*ARROW_AREA_HEIGHT, height - 2*ARROW_AREA_HEIGHT);
			trackY2 = height - ARROW_AREA_HEIGHT;
		}
		protected function updateHeight():void
		{
			arrowUp.y = 0;
			arrowDn.y = height;
			updateWindow();
		}
		override protected function setWindowValue(value:Number):void
		{
			super.setWindowValue(value);
			scrollStep = Math.max(0, Math.min(1-window, window));
		}
		
		
		override public function clean():void
		{
			removeArrowUp();
			removeArrowDn();
			removeSlider();
		}
		
		
		override protected function init():void
		{
			super.init();
		}
		override protected function createChildren():void
		{
			super.createChildren();
			
			createArrowUp();
			createArrowDn();
			createSlider();
		}
		protected function createArrowUp():void
		{
			//trace(this + ".createArrowUp(" + arguments + ")");
			//trace("classArrowUp=" + classArrowUp);
			
			arrowUp = new classArrowUp() as InteractiveObject;
			arrowUp.scaleY = 1;
			arrowUp.addEventListener(MouseEvent.CLICK, scrollUpInvoked);
			addChild(arrowUp);
		}
		protected function removeArrowUp():void
		{
			arrowUp.removeEventListener(MouseEvent.CLICK, scrollUpInvoked);
			if(contains(arrowUp))
			{
				removeChild(arrowUp);
			}
			arrowUp = null;
		}
		protected function createArrowDn():void
		{
			arrowDn = new classArrowDn() as InteractiveObject;
			if(flipArrowDnVertically)
			{
				arrowDn.scaleY = -1;
			}
			arrowDn.addEventListener(MouseEvent.CLICK, scrollDnInvoked);
			addChild(arrowDn);
		}
		protected function removeArrowDn():void
		{
			arrowDn.removeEventListener(MouseEvent.CLICK, scrollDnInvoked);
			if(contains(arrowDn))
			{
				removeChild(arrowDn);
			}
			arrowDn = null;
		}
		protected function createSlider():void
		{
			//trace(this + ".createSlider(" + arguments + ")");
			//trace("classSlider=" + classSlider);
			
			slider = new classSlider() as AbstractSlider;
			slider.addEventListener(MouseEvent.MOUSE_DOWN, sliderPress);
			slider.addEventListener(ScrollerEvent.SLIDER_MOVE, sliderDrag);
			slider.addEventListener(ScrollerEvent.SLIDER_RELEASE, sliderRelease);
			addChild(slider);
		}
		protected function removeSlider():void
		{
			slider.stopDrag();
			slider.removeEventListener(MouseEvent.MOUSE_DOWN, sliderPress);
			slider.removeEventListener(ScrollerEvent.SLIDER_MOVE, sliderDrag);
			slider.removeEventListener(ScrollerEvent.SLIDER_RELEASE, sliderRelease);
			if(contains(slider))
			{
				removeChild(slider);
			}
			slider = null;
		}
		override protected function completeInit():void
		{
			super.completeInit();
			height = height || HEIGHT_INITIAL;
		}
		protected function scrollUpInvoked(event:MouseEvent = null):void
		{
			scrollBy(-scrollStep);
			dispatchEvent(new ScrollerEvent(ScrollerEvent.SCROLL_INVOKED));
		}
		protected function scrollDnInvoked(event:MouseEvent = null):void
		{
			scrollBy(scrollStep);
			dispatchEvent(new ScrollerEvent(ScrollerEvent.SCROLL_INVOKED));
		}
		override protected function updateWindow():void
		{
			//trace(this + ".updateWindow(" + arguments + ")");
			//trace("trackHeight=" + trackHeight + "\twindow=" + window);
			slider.height = trackHeight*window;
		}
		override protected function updatePosition():void
		{
			//trace(this + ".updatePosition(" + arguments + ")");
			//trace("trackY1=" + trackY1 + "\ttrackHeight=" + trackHeight + "\tposition=" + position);
			slider.y = trackY1 + Math.max(0, trackHeight - slider.height)*position;
			//trace("slider._y=" + slider._y);
		}
		override protected function updateAccessibility():void
		{
			slider.mouseEnabled = enabled;
		}
	
		protected function sliderPress(event:MouseEvent):void
		{
			//trace(this + ".sliderPress(" + arguments + ")");
			//trace("trackY1=" + trackY1 + "\ttrackY2=" + trackY2 + "\ttrackY2-slider._height=" + (trackY2-slider._height));
			//slider.startDrag(false, slider.x, trackY1, slider.x, trackY2-slider.height);
			slider.startDrag(false, new Rectangle(slider.x, trackY1, 0, Math.max(0, trackHeight - slider.height)));
		}
		protected function sliderRelease(event:ScrollerEvent):void
		{
			slider.stopDrag();
		}
		protected function sliderDrag(event:ScrollerEvent):void
		{
			//trace(this + ".sliderDrag(" + arguments + ")");
			scrollTo(calculatePositionForSliderY(slider.y), true);
			dispatchEvent(new ScrollerEvent(ScrollerEvent.SCROLL_INVOKED));
		}
		protected function calculatePositionForSliderY(y:Number = undefined):Number
		{
			if(isNaN(y))
			{
				y = slider.y;
			}
			var localSliderTravel:Number = Math.max(0, trackHeight - slider.height);
			return (localSliderTravel==0 ? 0 : ((y - trackY1)/localSliderTravel));
		}
		
		
		override public function toString():String
		{
			return "[com.bizmlib.ui.scrolling.SimpleScroller height:" + height + " slider.height=" + slider.height + " slider.y=" + slider.y + "]";
		}
	}
}